﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Web.Script.Serialization;
using MyBlog.Common;
using MyBlog.Model;

namespace MyBlog.Web.Controllers
{
    public class AccountController : BaseController
    {
        [TrackRequest]
        public ActionResult Login()
        {
            if (UserSession.IsLogin)
            {
                return Redirect("/");
            }
            return View();
        }

        [HttpPost]
        public JsonResult CheckIsLogin()
        {
            return Json(new { IsLogin = UserSession.IsLogin });
        }

        [HttpPost]
        public ActionResult Login(AccountModel user, bool? isRemember)
        {
            var account = XiaoBoKe.AccountService.Get(user);
            if (null == account)
            {
                return Json(new JsonData { State = AjaxState.Fail, Message = "*用户名或密码错误" });
            }
            else
            {
                if (WebCache.NeedActive && !account.IsActive)
                {
                    return Json(new JsonData { State = AjaxState.Fail, Message = "*用户未激活，请激活" });
                }
                if (user.Password.Length == 32
                    && (CookieHelper.GetCookie("userinfo") == null || (!CookieHelper.GetCookie("userinfo").Values["account"].ToString().Same(user.Account)))
                    && !user.IsEncrypt)
                {
                    return Json(new JsonData { State = AjaxState.Fail, Message = "*非法登入操作" });
                }
                UserSession.SaveSession(account, isRemember);
                //登录强制刷新缓存
                WebCache.Refresh();
                var url = Url.Content("~/" + user.Account.ToLower());
                if (Request.QueryString["ReturnUrl"] != null)
                {
                    url = Url.Content(Request.QueryString["ReturnUrl"].ToString());
                }
                return Json(new JsonData { State = AjaxState.Success, Url = url });
            }
        }

        const string QQ_APPID = "";
        const string QQ_APPKEY = "";
        const string WB_APPID = "";
        const string WB_APPKEY = "";

        [HttpPost]
        public JsonResult ThirdLogin(string code, string state)
        {
            //传入的code为第一步获取到的
            if (state.Same("qq"))
            {
                #region QQ登录
                var javaScriptSerializer = new JavaScriptSerializer();
                var tokenUrl = "https://graph.qq.com/oauth2.0/token?grant_type=authorization_code&client_id="
                           + QQ_APPID + "&client_secret=" + QQ_APPKEY + "&code=" + code + "&redirect_uri=" + HttpUtility.UrlEncode("http://www.xiaoboke.net/qc_back.html");
                var tokenRequest = WebRequest.Create(tokenUrl) as HttpWebRequest;
                tokenRequest.Method = "GET";
                var r1 = (HttpWebResponse)tokenRequest.GetResponse();
                using (var readerToken = new StreamReader(r1.GetResponseStream(), Encoding.UTF8))
                {
                    //第二步：这里将获得access_token授权码
                    var tokenResult = readerToken.ReadToEnd();
                    var token = tokenResult.Split('&')[0].Replace("access_token=", "");
                    var openIdRequest = WebRequest.Create("https://graph.qq.com/oauth2.0/me?access_token=" + token) as HttpWebRequest;
                    openIdRequest.Method = "GET";
                    var r2 = (HttpWebResponse)openIdRequest.GetResponse();
                    using (var readerOpenid = new StreamReader(r2.GetResponseStream(), Encoding.UTF8))
                    {
                        //第三步：这里将获得openid标识
                        var openidstr = readerOpenid.ReadToEnd();
                        openidstr = openidstr.Replace("callback(", "").Replace(");", "").Trim();
                        var info = javaScriptSerializer.Deserialize<Dictionary<string, string>>(openidstr);
                        var openid = info["openid"];
                        var lastUrl = "https://graph.qq.com/user/get_user_info?access_token=" + token + "&oauth_consumer_key=" + QQ_APPID + "&openid=" + openid;
                        var lastRequest = WebRequest.Create(lastUrl) as HttpWebRequest;
                        lastRequest.Method = "GET";
                        var r3 = (HttpWebResponse)lastRequest.GetResponse();
                        using (var readerUser = new StreamReader(r3.GetResponseStream(), Encoding.UTF8))
                        {
                            //第四步：这里将获得QQ用户信息
                            var infojson = readerUser.ReadToEnd();
                            var userinfo = javaScriptSerializer.Deserialize<Dictionary<string, string>>(infojson);
                            var nickname = userinfo["nickname"];
                            var gender = userinfo["gender"];
                            var headUrl = userinfo["figureurl_2"];
                            var qqHead = userinfo["figureurl_qq_2"];
                            if (!string.IsNullOrWhiteSpace(qqHead))
                            {
                                headUrl = qqHead;
                            }
                            //后台数据保存逻辑
                            var uid = SaveThirdLoginData(state, openid, nickname, gender, headUrl);
                            return Json(new JsonData { State = AjaxState.Success, Url = Url.Content("~/" + uid) });
                        }
                    }
                }
                #endregion
            }
            if (state.Same("wb"))
            {
                #region 新浪微博登录
                //根据code获得access_token和uid
                var tokenUrl = "https://api.weibo.com/oauth2/access_token";
                var parms = new { grant_type = "authorization_code", client_id = WB_APPID, client_secret = WB_APPKEY, code = code, redirect_uri = "http://www.xiaoboke.net/qc_back.html" };
                var tokenInfo = ExtensionMethod.SendHttpPost(tokenUrl, parms).JsonToDictionary();
                var access_token = tokenInfo["access_token"].ToString();
                var uid = tokenInfo["uid"].ToString();
                //根据access_token和uid获取微博用户信息
                var userUrl = "https://api.weibo.com/2/users/show.json";
                var userinfo = ExtensionMethod.SendHttpGet(userUrl, new { access_token = access_token, uid = uid }).JsonToDictionary();
                var nickname = userinfo["name"].ToString();
                var gender = userinfo["gender"].ToString() == "m" ? "男" : "女";
                var headUrl = userinfo["avatar_large"].ToString();
                //后台数据保存逻辑
                var newUID = SaveThirdLoginData(state, uid, nickname, gender, headUrl);
                return Json(new JsonData { State = AjaxState.Success, Url = Url.Content("~/" + newUID) });
                #endregion
            }
            return Json(new JsonData { State = AjaxState.Success });
        }

        /// <summary>
        /// 第三方登录数据保存逻辑
        /// </summary>
        /// <param name="state"></param>
        /// <param name="openid"></param>
        /// <param name="nickname"></param>
        /// <param name="sex"></param>
        /// <param name="headUrl"></param>
        /// <returns>返回用户id</returns>
        string SaveThirdLoginData(string state, string openid, string nickname, string gender, string headUrl)
        {
            var uid = (state == "qq" ? "QQ_" : "WB_") + openid.MD5_16();
            var user = XiaoBoKe.AccountService.Get(uid);
            if (user == null)
            {
                byte[] hBytes = null;
                try
                {
                    hBytes = new WebClient().DownloadData(headUrl);
                }
                catch (Exception ex)
                {
                    LogHelper.WriteLog("获取用户头像出错：" + ex.Message);
                }
                user = new AccountModel
                {
                    IsActive = true,
                    Account = uid,
                    Password = openid,
                    NickName = nickname,
                    Sex = gender == "男",
                    Template = (gender == "男" ? TemplateEnum.boy : TemplateEnum.girl),
                    RegTime = DateTime.Now,
                    LastLoginTime = DateTime.Now,
                    Email = "third@third.com"
                };
                if (hBytes != null)
                {
                    user.Header = new HeaderModel { ContentType = "image/jpeg", ImageContent = hBytes, Size = hBytes.Length / 1024 + "KB" };
                }
                XiaoBoKe.AccountService.Add(user);
            }
            UserSession.SaveSession(user, false);
            WebCache.Refresh();
            base.AddNotice(UserSession.AccountId, NoticeEnum.Register, null, "系统消息：亲爱的用户，欢迎您注册小博客！");
            return user.Account;
        }

        public ActionResult LogOff()
        {
            UserSession.ClearSession();
            return Redirect("/");
        }

        [TrackRequest]
        public ActionResult Register()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Register(AccountModel user, string code)
        {
            if (Session["ValidateCode"] == null || string.IsNullOrWhiteSpace(code))
            {
                return Json(new JsonData { State = AjaxState.Fail, Message = "*请输入验证码" });
            }
            if (Session["ValidateCode"].ToString().ToLower() != code.ToLower())
            {
                return Json(new JsonData { State = AjaxState.Fail, Message = "*输入的验证码不正确" });
            }
            user.Motto = "愿有人陪你颠沛流离，如果没有，愿你成为自己的太阳。";
            string notice = null;
            if (WebCache.NeedActive)
            {
                user.ActiveCode = WebCache.CreateActiveCode(user.Account);
                var passToken = user.Password.EncryptDES();
                XiaoBoKe.AccountService.Add(user);
                notice = "亲爱的用户，你的注册激活码是：{0}，请在注册页面输入这个激活码进行帐号激活。".FormatStr(user.ActiveCode);
                EmailHelper.SendMail(user.Email, "小博客注册激活码", notice);
                return Json(new JsonData { State = AjaxState.NeedActive, Data = new { token = user.ActiveCode.MD5_16(), token2 = passToken } });
            }
            else
            {
                user.IsActive = true;
                notice = "亲爱的{0}，欢迎您注册小博客！<br/>你的登录用户名是：{1}，你的密码是：{2}<br/>请牢记你的用户名和密码。<a target='_blank' href='{3}'>点此进入我的博客</a>"
                .FormatStr(user.NickName, user.Account, user.Password, WebCache.SystemHost + "/" + user.Account);
                XiaoBoKe.AccountService.Add(user);
                UserSession.SaveSession(user, false);
                WebCache.Refresh();
                EmailHelper.SendMail(user.Email, "欢迎您注册小博客！", notice);
                base.AddNotice(UserSession.AccountId, NoticeEnum.Register, null, "系统消息：亲爱的用户，欢迎您注册小博客！");
                return Json(new JsonData { State = AjaxState.Success, Url = Url.Content("~/" + user.Account.ToLower() + "?first=true") });
            }
        }

        [HttpPost]
        [ActionName("active")]
        public JsonResult ActiveUser(string account, string activeCode, string token)
        {
            var user = XiaoBoKe.AccountService.Get(account);
            if (user.ActiveCode.Same(activeCode))
            {
                XiaoBoKe.AccountService.Active(user.Account);
                UserSession.SaveSession(user, false);
                WebCache.Refresh();
                var notice = "亲爱的{0}，欢迎您注册小博客！<br/>你的登录用户名是：{1}，你的密码是：{2}<br/>请牢记你的用户名和密码。<a target='_blank' href='{3}'>点此进入我的博客</a>"
                .FormatStr(user.NickName, user.Account, token.DecryptDES(), WebCache.SystemHost + "/" + user.Account);
                EmailHelper.SendMail(user.Email, "欢迎您注册小博客！", notice);
                base.AddNotice(UserSession.AccountId, NoticeEnum.Register, null, "系统消息：亲爱的用户，欢迎您注册小博客！");
                return Json(new JsonData { State = AjaxState.Success, Url = Url.Content("~/" + user.Account.ToLower() + "?first=true") });
            }
            else
            {
                return Json(new JsonData { State = AjaxState.Fail, Message = "激活码匹配失败" });
            }
        }

        [HttpPost]
        public JsonResult SendActiveCode(string account)
        {
            var user = XiaoBoKe.AccountService.Get(account);
            var notice = "亲爱的用户，你的注册激活码是：{0}，请在注册页面输入这个激活码进行帐号激活。".FormatStr(user.ActiveCode);
            EmailHelper.SendMail(user.Email, "小博客注册激活码", notice);
            return Json(new JsonData { State = AjaxState.Success });
        }

        [Authenticate(false)]
        [HttpPost]
        public ActionResult ResetPwd(string passOld, string pass, string pass2)
        {
            if (string.IsNullOrWhiteSpace(pass) || string.IsNullOrWhiteSpace(pass2) || (pass != pass2))
            {
                return Json(new JsonData { State = AjaxState.Fail, Message = "新密码校验失败" });
            }
            var model = new AccountModel { Account = UserSession.AccountId, Password = passOld };
            var user = XiaoBoKe.AccountService.Get(model);
            if (user == null)
            {
                return Json(new JsonData { State = AjaxState.Fail, Message = "你输入的原密码不正确" });
            }
            model.Password = pass;
            XiaoBoKe.AccountService.UpdatePassword(model);
            return Json(new JsonData { State = AjaxState.Success });
        }

        public ActionResult FindPwd()
        {
            return View();
        }

        [HttpPost]
        public ActionResult GetSecurityCode(string account, string email)
        {
            string key = account.Trim().ToLower() + "secCode";
            var user = XiaoBoKe.AccountService.Get(new AccountModel { Account = account, Email = email });
            if (null == user)
            {
                return Json(new JsonData { State = AjaxState.Fail, Message = "系统中不存在这个用户，请检查用户名和邮箱是否有误" });
            }
            int timeOut = 30;
            var code = new Random().Next(222222, 888888).ToString();
            if (CookieHelper.GetCookie(key) != null)
            {
                code = CookieHelper.GetCookie(key).Value;
            }
            //验证码10分钟后失效
            CookieHelper.AddCookie(key, code, DateTime.Now.AddMinutes(timeOut));
            var notice = "尊敬的用户，你本次操作的验证码是：" + code + "，" + timeOut + "分钟内输入有效，请勿泄漏验证码给他人。";
            EmailHelper.SendMail(email, "小博客验证码", notice);
            return Json(new JsonData { State = AjaxState.Success, Data = new { code = code } });
        }

        [HttpPost]
        public ActionResult PassReset(string account, string email, string code)
        {
            string key = account.Trim().ToLower() + "secCode";
            if (CookieHelper.GetCookie(key) != null && !string.IsNullOrWhiteSpace(CookieHelper.GetCookie(key).Value))
            {
                if (!CookieHelper.GetCookie(key).Value.Same(code))
                {
                    return Json(new JsonData { State = AjaxState.Fail, Message = "你输入的验证码不正确" });
                }
                var pass = new Random().Next(111111, 999999).ToString();
                var user = XiaoBoKe.AccountService.Get(account);
                user.Password = pass;
                XiaoBoKe.AccountService.UpdatePassword(user);
                var notice = "尊敬的用户，帐号" + user.Account + "申请找回密码操作已成功，系统已将你的密码重置为：" + pass + "，请你尽快使用这个密码登录你的博客并在【个人信息设置=》安全设置】中修改密码。";
                EmailHelper.SendMail(email, "找回密码处理结果", notice);
                return Json(new JsonData { State = AjaxState.Success });
            }
            else
            {
                return Json(new JsonData { State = AjaxState.Fail, Message = "未获取验证码或验证码已失效，请重新获取验证码" });
            }
        }

        public ActionResult CheckUser(AccountModel model)
        {
            try
            {
                if (model.Islogin)
                {
                    return Json(true, JsonRequestBehavior.AllowGet); ;
                }
                var user = XiaoBoKe.AccountService.Get(model.Account);
                return Json(user == null, JsonRequestBehavior.AllowGet);
            }
            catch
            {
                return Json("用户名检验出错啦", JsonRequestBehavior.AllowGet);
            }
        }

        [HttpPost]
        public ActionResult CancelReg(string account, string token)
        {
            var user = XiaoBoKe.AccountService.Get(account);
            if (user.ActiveCode != null && user.ActiveCode.MD5_16().Same(token))
            {
                XiaoBoKe.AccountService.Delete(account);
                return Json(new JsonData { State = AjaxState.Success });
            }
            else
            {
                return Json(new JsonData { State = AjaxState.Fail, Message = "非法操作！" });
            }
        }

        public FileContentResult GetUserHeadByUid(string uid)
        {
            var user = WebCache.GetAccount(uid) ?? new AccountModel();
            var bytes = user.HeadId.HasValue ? user.Header.ImageContent : ExtensionMethod.GetDefaultHeadBytes(45, 45);
            string contentType = user.HeadId.HasValue ? user.Header.ContentType : "jpg";
            return File(bytes, contentType);
        }

        public ActionResult GetValidateCode()
        {
            ValidateCode vCode = new ValidateCode();
            string code = vCode.CreateValidateCode(5);
            Session["ValidateCode"] = code;
            byte[] bytes = vCode.CreateValidateGraphic(code);
            return File(bytes, @"image/jpeg");
        }
    }
}
